<template>
  <div>
    <canvas ref="canvas"
            style="height: 100vh;width: 100%;background-image: linear-gradient(-225deg, #2C73D2 0%, #36156b 29%, #B0A8B9 100%)"></canvas>
  </div>
</template>
<script setup>
import {ref, onMounted} from 'vue';

const canvas = ref(null);
let context = ref(null);
let width = ref(null);
let height = ref(null);
onMounted(() => {
  if (canvas.value) {
    context = canvas.value.getContext("2d");
    canvas.value.addEventListener('mousemove', onMouseMove);
    // canvas.value.addEventListener('ontouchmove', onTouchMove);
    // canvas.value.addEventListener('ontouchend', onTouchMove);
    // 生成星星
    generate();
    // 调整大小
    resize();
    // 运行动画
    step();
  }
  // 当鼠标离开文档时，更新鼠标指针位置
  // document.onmouseleave = onMouseLeave;
})

const STAR_COLOR = '#fff';
//   // 定义星星的大小
const STAR_SIZE = 1.2;
//   // 定义星星的最小缩放比例
const STAR_MIN_SCALE = 0.6;
//   // 定义溢出阈值
const OVERFLOW_THRESHOLD = 50;
//   // 定义星星的数量
const STAR_COUNT = (window.innerWidth + window.innerHeight) * 4;
//   // 获取canvas元素
//   // 获取canvas的绘图上下文
//
//   // 定义缩放比例
let scale = 1; // device pixel ratio
//   // 定义宽度和高度
//   // 定义星星数组
let stars = [];
//   // 定义鼠标指针的位置
let pointerX;
let pointerY;
//   // 定义速度对象
let velocity = {
  x: 0,
  y: 0,
  tx: 0,
  ty: 0,
  z: 0.0009
};
//   // 定义触摸输入标志
let touchInput = false;
//
//   // 当窗口大小改变时，重新调整大小
window.onresize = resize;
//   // 当鼠标离开文档时，更新鼠标指针位置
//   document.onmouseleave = onMouseLeave;
//
//   // 生成星星
function generate() {
  for (let i = 0; i < STAR_COUNT; i++) {
    stars.push({
      x: 0,
      y: 0,
      z: STAR_MIN_SCALE + Math.random() * (1 - STAR_MIN_SCALE),
    });
  }
}

//
//   // 将星星放置到随机位置
function placeStar(star) {
  star.x = Math.random() * width;
  star.y = Math.random() * height;
}

//
//   // 回收星星并重新放置到新的位置
function recycleStar(star) {
  // 初始化方向为 'z'
  let direction = 'z';
  // 获取速度的绝对值
  let vx = Math.abs(velocity.x);
  let vy = Math.abs(velocity.y);
  // 如果速度的绝对值大于1，则根据速度的大小随机确定方向
  if (vx > 1 || vy > 1) {
    let axis;
    // 如果水平速度大于垂直速度，则根据水平速度的比例随机确定水平或垂直方向
    if (vx > vy) {
      axis = Math.random() < vx / (vx + vy) ? 'h' : 'v';
    } else {
      axis = Math.random() < vy / (vx + vy) ? 'v' : 'h';
    }
    // 根据方向确定具体的移动方向
    if (axis === 'h') {
      direction = velocity.x > 0 ? 'l' : 'r';
    } else {
      direction = velocity.y > 0 ? 't' : 'b';
    }
  }
  // 随机设置星星的缩放比例
  star.z = STAR_MIN_SCALE + Math.random() * (1 - STAR_MIN_SCALE);
  // 根据方向设置星星的位置
  if (direction === 'z') {
    // 如果方向为 'z'，则将星星放置在屏幕中心
    star.z = 0.1;
    star.x = Math.random() * width;
    star.y = Math.random() * height;
  } else if (direction === 'l') {
    // 如果方向为 'l'，则将星星放置在屏幕左侧
    star.x = -OVERFLOW_THRESHOLD;
    star.y = height * Math.random();
  } else if (direction === 'r') {
    // 如果方向为 'r'，则将星星放置在屏幕右侧
    star.x = width + OVERFLOW_THRESHOLD;
    star.y = height * Math.random();
  } else if (direction === 't') {
    // 如果方向为 't'，则将星星放置在屏幕顶部
    star.x = width * Math.random();
    star.y = -OVERFLOW_THRESHOLD;
  } else if (direction === 'b') {
    // 如果方向为 'b'，则将星星放置在屏幕底部
    star.x = width * Math.random();
    star.y = height + OVERFLOW_THRESHOLD;
  }
}

//
//   // 调整大小
function resize() {
  // 获取设备像素比例
  scale = window.devicePixelRatio || 1;
  // 设置画布的宽度和高度
  width = window.innerWidth * scale;
  height = window.innerHeight * scale;
  // 将所有星星重新放置到屏幕上
  stars.forEach(placeStar);
}

//   // 动画的每一帧
function step() {
  // 清空画布
  context.clearRect(0, 0, width, height);
  // 更新星星的位置和速度
  update();
  // 绘制星星
  render();
  // 请求下一帧动画
  requestAnimationFrame(step);
}

//
//   // 更新星星的位置和速度
function update() {
  // 缓动速度
  velocity.tx *= 0.7;
  velocity.ty *= 0.7;
  // 更新速度
  velocity.x += (velocity.tx - velocity.x) * 0.8;
  velocity.y += (velocity.ty - velocity.y) * 0.8;
  // 遍历所有星星
  stars.forEach((star) => {
    // 根据速度和缩放比例更新星星的位置
    star.x += velocity.x * star.z;
    star.y += velocity.y * star.z;
    // 根据速度和缩放比例更新星星的位置（使星星围绕屏幕中心旋转）
    star.x += (star.x - width / 2) * velocity.z * star.z;
    star.y += (star.y - height / 2) * velocity.z * star.z;
    // 更新星星的缩放比例
    star.z += velocity.z;
    // 如果星星超出屏幕范围，则重新放置到屏幕上
    if (
        star.x < -OVERFLOW_THRESHOLD ||
        star.x > width + OVERFLOW_THRESHOLD ||
        star.y < -OVERFLOW_THRESHOLD ||
        star.y > height + OVERFLOW_THRESHOLD
    ) {
      recycleStar(star);
    }
  });
}

//
//   // 绘制星星
function render() {
  // 遍历所有星星
  stars.forEach((star) => {
    // 设置绘制星星的样式
// 开始一个新的路径。在绘制之前，这通常用于清除之前的路径或确保接下来绘制的形状是独立的。
    context.beginPath();
// 设置线条的端点样式为圆形。这样线条的结束处将会是圆形的，而不是默认的方形或斜切。
    context.lineCap = 'round';
// 设置线条的宽度。这里使用了STAR_SIZE常量乘以star.z的值（可能是星星的深度或位置），然后再乘以一个scale比例因子。
// 这样做可以根据星星的深度或位置动态调整线条的宽度。
    context.lineWidth = STAR_SIZE * star.z * scale;
// 设置全局透明度。这里使用了0.5作为基准，然后加上0到0.5之间的一个随机数，使得线条的透明度在0.5到1之间随机变化。
// 这可以为星星的绘制添加一些随机性的视觉效果。
    context.globalAlpha = 0.5 + 0.5 * Math.random();
// 设置线条的颜色。这里使用了STAR_COLOR常量，它可能是一个预定义的颜色值，用于绘制星星的线条。
    context.strokeStyle = STAR_COLOR;
    // 绘制星星的路径
    context.beginPath();
    // context.arc(half, half, half, 0, Math.PI * 2);
    // context.fill();
    context.moveTo(star.x, star.y);
    // 计算星星的尾巴坐标
    let tailX = velocity.x * 2;
    let tailY = velocity.y * 2;
    // 如果尾巴坐标的绝对值小于0.1，则设置为0.5
    if (Math.abs(tailX) < 0.1) tailX = 0.5;
    if (Math.abs(tailY) < 0.1) tailY = 0.5;
    // 绘制星星的尾巴
    context.lineTo(star.x + tailX, star.y + tailY);
    context.stroke();
  });
}

//
//   // 移动鼠标指针
function movePointer(x, y) {
  // 如果之前有记录鼠标指针的位置，则计算鼠标指针的移动距离，并更新速度
  if (typeof pointerX === 'number' && typeof pointerY === 'number') {
    let ox = x - pointerX;
    let oy = y - pointerY;
    velocity.tx = velocity.tx + (ox / 10) * scale * (touchInput ? 1 : -1);
    velocity.ty = velocity.ty + (oy / 10) * scale * (touchInput ? 1 : -1);
  }
  // 更新鼠标指针的位置
  pointerX = x;
  pointerY = y;
}

//
//   // 当鼠标在canvas上移动时的事件处理函数
function onMouseMove(event) {
  touchInput = true;
  movePointer(event.clientX, event.clientY);
}

//
//   // 当触摸屏在canvas上移动时的事件处理函数
//   function onTouchMove(event) {
//     touchInput = true;
//     movePointer(event.touches[0].clientX, event.touches[0].clientY, true);
//     event.preventDefault();
//   }
//
//   // 当鼠标离开canvas时的事件处理函数
function onMouseLeave() {
  pointerX = null;
  pointerY = null;
}
</script>

<style>
.canvas-container {
  position: relative;
  width: 100%;
  height: 100%;
}
</style>


<style scoped>
html {
  height: 100%;
  background-image: -webkit-radial-gradient(ellipse farthest-corner at center top, #000d4d 0%, #000105 100%);
  background-image: radial-gradient(ellipse farthest-corner at center top, #000d4d 0%, #000105 100%);
  cursor: move;
}

body {
  width: 100%;
  margin: 0;
  overflow: hidden;
}
</style>
